#include "TileEngine.h"

#include "Player.h"
#include "Camera.h"
#include "Tile.h"
#include "Layer.h"
#include "tinyxml.h"

#include "../SGD Wrappers/SGD_GraphicsManager.h"


TileEngine::TileEngine(){

	//	Load textures
	_grass = SGD::GraphicsManager::GetInstance()->LoadTexture(L"resource/graphics/MapTextures/GrassTexture.png");
	_blueflower = SGD::GraphicsManager::GetInstance()->LoadTexture(L"resource/graphics/MapTextures/BlueFlower.png");
	_sand = SGD::GraphicsManager::GetInstance()->LoadTexture(L"resource/graphics/MapTextures/Sand.png");
	_collision = SGD::GraphicsManager::GetInstance()->LoadTexture(L"resource/graphics/MapTextures/CollisionTerrain.png");

		//	Initialize Cam
	m_camera = new Camera();
	m_mapLayer = new Layer();

		//	Clear tiles vec
	m_tiles.empty();
}

TileEngine::~TileEngine(){
		//	delete each tile
	for (unsigned int x = 0; x < m_tiles.size(); ++x)
		delete m_tiles[x];

	m_tiles.clear();

	SGD::GraphicsManager::GetInstance()->UnloadTexture(_grass);
	SGD::GraphicsManager::GetInstance()->UnloadTexture(_blueflower);
	SGD::GraphicsManager::GetInstance()->UnloadTexture(_sand);
	SGD::GraphicsManager::GetInstance()->UnloadTexture(_collision);

	delete m_camera;
	delete m_mapLayer;
}

void TileEngine::Update(float elapsedTime){
	m_camera->Update(elapsedTime, m_WorldSize);
}

void TileEngine::Render(){

	SGD::GraphicsManager* graphics = SGD::GraphicsManager::GetInstance();

	for (unsigned int x = 0; x < m_tiles.size(); ++x){
		//	Render tiles withing camera offset
		SGD::Point p = SGD::Point(m_tiles.at(x)->GetWorldPosition().x - m_camera->GetCameraOffset().x,
			m_tiles.at(x)->GetWorldPosition().y - m_camera->GetCameraOffset().y);

		//	Auto - scale tiles based on width x height
		SGD::Size tileScale = SGD::Size(
			m_TileSize.width / 16.0f,
			m_TileSize.height / 16.0f);


		//	Tile Culling
		if (p.x > -32 && p.x < 1024 - p.x + 1020 && p.y > -32 && p.y < 768 - p.y + 764){
			switch (m_tiles.at(x)->GetTileType()){

			case E_GRASS:
				graphics->DrawTexture(_grass, p, 0.0f, {}, {}, tileScale);
				break;
			case E_SAND:
				graphics->DrawTexture(_sand, p, 0.0f, {}, {}, tileScale);
				break;
			case E_BLUEFLOWER:
				graphics->DrawTexture(_blueflower, p, 0.0f, {}, {}, tileScale);
				break;
			case E_IMPASSABLE:
			{
				SGD::Point bot = SGD::Point(p.x + m_TileSize.width, p.y + m_TileSize.height);

				SGD::Rectangle rect = SGD::Rectangle(p, bot);

				m_tiles.at(x)->SetTileRect(rect);
				graphics->DrawTexture(_collision, p, 0.0f, {}, {}, tileScale);
			}
				break;
			default:
				//graphics->DrawTexture(_grass, p, 0.0f, {}, {}, tileScale);
				break;
			}
		}
	}

	/*for (unsigned int r = 0; r < m_mapLayer->GetCollisionPoints().size(); ++r){

		SGD::Rectangle tmp = SGD::Rectangle(m_mapLayer->GetCollisionPoints().at(r).x - m_camera->GetCameraOffset().x,
			m_mapLayer->GetCollisionPoints().at(r).y - m_camera->GetCameraOffset().y, 0, 0);
		tmp.right = tmp.left + 32;
		tmp.bottom = tmp.top + 32;

		if (!tmp.IsEmpty())
			graphics->DrawRectangle(tmp, SGD::Color(0, 255, 255, 255), SGD::Color(255, 0, 0), 1);
	}*/
}


void TileEngine::LoadMap(const char* filename){

		//	Initialize and load Doc
	TiXmlDocument doc(filename);
	if (!doc.LoadFile()) return;

		//	Doc's handle
	TiXmlHandle hDoc(&doc);

		//	Root of the xml doc
	TiXmlElement* root;
	root = hDoc.ChildElement(0).Element();
	if (!root) return;

		//	Root's child
	TiXmlElement* element = root->FirstChildElement();

		//	Children of element
	element = element->FirstChildElement();

	{	//	Tile Engine Settings
		float tmprow;
		float tmpcol;
		float tilewidth;
		float tileheight;
		float tmpwidth;
		float tmpheight;

		element->QueryFloatAttribute("Row", &tmprow);
		element->QueryFloatAttribute("Col", &tmpcol);
		element->QueryFloatAttribute("TileWidth", &tilewidth);
		element->QueryFloatAttribute("TileHeight", &tileheight);
		element->QueryFloatAttribute("WorldWidth", &tmpwidth);
		element->QueryFloatAttribute("WorldHeight", &tmpheight);

		SetGridSize(SGD::Size(tmpcol, tmprow));
		SetTileSize(SGD::Size(tilewidth, tileheight));
		SetWorldSize(SGD::Size(tmpwidth, tmpheight));
	}

	element = element->NextSiblingElement();
	while (element != NULL) {

		float tmprow;
		float tmpcol;
		int tmptype;

		element->QueryFloatAttribute("Row", &tmprow);
		element->QueryFloatAttribute("Col", &tmpcol);
		element->QueryIntAttribute("Type", &tmptype);

		SGD::Point gridpos = SGD::Point(tmpcol, tmprow);
		SGD::Point worldpos = SGD::Point(tmpcol * m_TileSize.width, tmprow * m_TileSize.height);
		Tile* tmp = new Tile(gridpos, worldpos, tmptype);

		m_tiles.push_back(tmp);
		element = element->NextSiblingElement();
	}
	InitializeLayer();
}

void TileEngine::SaveTestFile(){

		//	Xml doc Creation
	TiXmlDocument doc;

		//	Root of the xml
	TiXmlElement* root = new TiXmlElement("Map");
	doc.LinkEndChild(root);

		//	The root's child
	TiXmlElement* ele = new TiXmlElement("Tiles");
	root->LinkEndChild(ele);

		//	Children of ele
	TiXmlElement* data;

	unsigned int ROWS = 50;
	unsigned int COLS = 50;

	int size = 32;

	data = new TiXmlElement("WorldSettings");
	data->SetAttribute("Row", ROWS);
	data->SetAttribute("Col", COLS);
	data->SetAttribute("TileWidth", size);
	data->SetAttribute("TileHeight", size);
	data->SetAttribute("WorldWidth", ROWS * 32);
	data->SetAttribute("WorldHeight", COLS * 32);
	ele->LinkEndChild(data);

	for (unsigned int r = 0; r < ROWS; ++r) {
		for (unsigned int c = 0; c < COLS; ++c) {

			data = new TiXmlElement("Tile");
			data->SetAttribute("Col", c);
			data->SetAttribute("Row", r);
			int x = r % 3;
			if (c == 4 && r == 4)
				x = 4;
			data->SetAttribute("Type", x);	//	0 - 3
			ele->LinkEndChild(data);
		}
	}
	doc.SaveFile("testmap.xml");
}

void TileEngine::InitializeLayer(){
	for (unsigned int x = 0; x < m_tiles.size(); ++x){
		if (m_tiles.at(x)->GetTileType() == 3)
			m_mapLayer->AddCollisionPoints(m_tiles.at(x), m_TileSize);
	}

	for (unsigned int x = 0; x < m_tiles.size(); ++x){
		if (m_tiles.at(x)->GetTileType() == 4)
			m_mapLayer->SetStartTile(m_tiles.at(x));
	}	
}

void TileEngine::SetCamFocus(Entity* f){
	m_camera->SetCamFocus(f);
}